package com.redepronik.negosysres.invfac.controller;


import static com.redepronik.negosys.utils.Utils.parametro;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.context.RequestContext;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.SelectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Bodega;
import com.redepronik.negosys.invfac.entity.Detalleegreso;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Entrada;
import com.redepronik.negosys.invfac.entity.Kardex;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Motivobaja;
import com.redepronik.negosys.invfac.entity.Producto;
import com.redepronik.negosys.invfac.entity.TipoPrecioProducto;
import com.redepronik.negosys.invfac.entityAux.CantidadFactura;
import com.redepronik.negosys.invfac.entityAux.FacturaReporte;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.KardexService;
import com.redepronik.negosys.invfac.service.LocalService;
import com.redepronik.negosys.invfac.service.MotivoBajaService;
import com.redepronik.negosys.invfac.service.ProductoService;
import com.redepronik.negosys.invfac.service.TipoDocumentoService;
import com.redepronik.negosys.rrhh.service.EmpleadoService;

@Controller
@Scope("session")
public class BajaInventarioBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ProductoService productoService;

	@Autowired
	private KardexService kardexService;

	@Autowired
	private LocalService localService;

	@Autowired
	private MotivoBajaService motivoBajaService;

	@Autowired
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private EmpleadoService empleadoService;

	private List<Local> listaLocales;
	private List<Motivobaja> listaMotivoBajas;

	private Egreso egreso;

	private List<Producto> listProductos;
	private String nombreProducto;
	private Producto producto;

	private List<FacturaReporte> facturaReportes;
	private FacturaReporte facturaReporte;
	private CantidadFactura cantidadFacturaCalculos;
	private CantidadFactura cantidadFacturaPresentar;
	private Motivobaja motivoBaja;

	private Integer cantidad;

	private Bodega bodega;
	private TipoPrecioProducto tipoPrecioProducto;
	private Integer fila;

	private String login = "";
	private String pass = "";

	public BajaInventarioBean() {
		listProductos = new ArrayList<Producto>();

		producto = new Producto();
		facturaReportes = new ArrayList<FacturaReporte>();
		facturaReporte = new FacturaReporte();
		cantidadFacturaCalculos = new CantidadFactura();
		cantidadFacturaPresentar = new CantidadFactura();
		motivoBaja = new Motivobaja();
	}

	public void cambiarCantidad() {
		FacturaReporte f = facturaReportes.get(fila);
		int can = kardexService.obtenerSaldoActual(f.getCodigo(),
				bodega.getBodegaid()).getCantidad();

		if (cantidad <= can || cantidad > 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA",
					"INGRESE UNA CANTIDAD MENOR O IGUAL A LA EXISTENTE: " + can
							+ " O MAYOR QUE CERO"));
		else if (cantidad != f.getCantidad())
			facturaReportes.set(fila, egresoService.recalcular(fila, f,
					egreso.getDetalleegresos(), cantidadFacturaCalculos,
					cantidad, null, true));

		cantidad = null;
		fila = null;
	}

	public void cancelar() {
		facturaReporte = new FacturaReporte();
	}

	public void cancelarTodo() {
		xxx();
		facturaReportes = new ArrayList<FacturaReporte>();
		cantidadFacturaCalculos = new CantidadFactura();
	}

	public void cargarProducto(SelectEvent event) {
		producto = productoService.obtenerPorProductoId(producto
				.getProductoid());
		facturaReporte.setProductoId(producto.getProductoid());
		tipoPrecioProducto = producto.getTipoPrecioProductos().get(0);
		facturaReporte
				.setPrecioId(tipoPrecioProducto.getTipoprecioproductoid());
	}

	public boolean comprobar() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		if (egreso.getDetalleegresos().isEmpty()) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "DEBE INGRESAR DETALLES"));
		}

		if (bn)
			context.addCallbackParam("error", true);
		else
			context.addCallbackParam("error", false);

		return bn;
	}

	public boolean comprobarCantidadFinal() {
		boolean bn = true;

		List<Detalleegreso> detalleEgreso = new ArrayList<Detalleegreso>();
		for (Detalleegreso dE : egreso.getDetalleegresos()) {
			Detalleegreso dEgreso = new Detalleegreso();
			dEgreso.setCantidad(dE.getCantidad());
			dEgreso.setPrecioventa(dE.getPrecioventa());
			dEgreso.setPreciocosto(dE.getPreciocosto());
			dEgreso.setEliminar(dE.getEliminar());
			dEgreso.setPromocion(dE.getPromocion());
			dEgreso.setProducto(dE.getProducto());
			detalleEgreso.add(dEgreso);
		}

		List<Detalleegreso> detalleEgresoFinal = egresoService
				.sumarCantidades(detalleEgreso);
		for (Detalleegreso de : detalleEgresoFinal) {

			Producto producto = productoService.obtenerPorProductoId(de
					.getProducto().getProductoid());

			int cantidad = kardexService.obtenerSaldoActual(producto.getEan(),
					bodega.getBodegaid()).getCantidad();

			if (de.getCantidad() > cantidad) {
				bn = false;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA",
						"LA SUMA DE LAS CANTIDADES DEL PRODUCTO: "
								+ producto.getEan() + " ES MAYOR A: "
								+ cantidad));
			}
		}

		return bn;
	}

	public void comprobarClienteLocal() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		if (egreso.getLocal().getLocalid() == null) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "DEBE ESCOJER UN LOCAL"));
		}
		if (egreso.getLocal().getLocalid() != null) {
			Local local = localService.obtenerPorLocalId(egreso.getLocal()
					.getLocalid());
			if (local.getBodegalocals() == null
					&& local.getBodegalocals().isEmpty()) {
				bn = false;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
						"MENSAJE DEL SISTEMA",
						"EL LOCAL QUE ESCOJIO NO TIENE BODEGAS ASOCIADAS"));
			}
		}

		if (bn)
			context.addCallbackParam("error1", true);
		else
			context.addCallbackParam("error1", false);
	}

	public void comprobarTodo() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		bn = comprobarCantidadFinal();
		bn = comprobar();

		if (bn)
			context.addCallbackParam("error2", true);
		else
			context.addCallbackParam("error2", false);

	}

	public void eliminarDetalle(ActionEvent actionEvent) {
		int posicion = egresoService.posicion(facturaReporte,
				egreso.getDetalleegresos(), true);
		if (posicion >= 0) {
			Detalleegreso de = egreso.getDetalleegresos().get(posicion);
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"ELIMINÓ DETALLE", "Elimino: " + de.getProducto().getEan()));
			egreso.removeDetalleegreso(de);
			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, facturaReporte, "subtract");
			facturaReportes.remove(facturaReporte);
			cancelar();
		}
	}

	public Integer getCantidad() {
		return cantidad;
	}

	public CantidadFactura getCantidadFacturaCalculos() {
		return cantidadFacturaCalculos;
	}

	public CantidadFactura getCantidadFacturaPresentar() {
		return egresoService.redondearCantidadFactura(cantidadFacturaPresentar,
				cantidadFacturaCalculos);
	}

	public Egreso getEgreso() {
		return egreso;
	}

	public FacturaReporte getFacturaReporte() {
		return facturaReporte;
	}

	public List<FacturaReporte> getFacturaReportes() {
		return facturaReportes;
	}

	public List<Local> getListaLocales() {
		return listaLocales;
	}

	public List<Motivobaja> getListaMotivoBajas() {
		return listaMotivoBajas;
	}

	public List<Producto> getListProductos() {
		return listProductos;
	}

	public String getLogin() {
		return login;
	}

	public Motivobaja getMotivoBaja() {
		return motivoBaja;
	}

	public String getNombreProducto() {
		return nombreProducto;
	}

	public String getPass() {
		return pass;
	}

	public Producto getProducto() {
		return producto;
	}

	@PostConstruct
	public void init() {
		setListaLocales(localService.obtenerPorCajero(SecurityContextHolder
				.getContext().getAuthentication().getName()));
		setListaMotivoBajas(motivoBajaService.obtener(null));
		xxx();
	}

	public void insertar(ActionEvent actionEvent) {
		if (comprobarCantidadFinal() && comprobar()) {
			Map<String, Object> parametro = empleadoService.autorizacion(login,
					pass);
			login = "";
			pass = "";
			presentaMensaje((FacesMessage) parametro.get("mensaje"));
			Boolean bn = (Boolean) parametro.get("correcto");
			if (bn) {
				egreso.setPagado(false);
				egreso.setCliente(null);
				egresoService.insertar(egreso, bodega);
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA", "INSERTÓ Egreso: "
								+ egreso.getCodigodocumento()));

				cancelarTodo();
			}
		}
	}

	public void insertarDetalle(ActionEvent actionEvent) {
		producto = productoService.obtenerPorProductoId(producto
				.getProductoid());

		Kardex kardex = kardexService.obtenerSaldoActual(producto.getEan(),
				bodega.getBodegaid());

		if (facturaReporte.getCantidad() <= kardex.getCantidad()
				&& facturaReporte.getCantidad() > 0) {
			Detalleegreso detalleEgreso = new Detalleegreso();

			detalleEgreso.setProducto(producto);
			detalleEgreso.setMotivobaja(motivoBajaService
					.obtenerPorMotivoBajaId(motivoBaja.getMotivobajaid()));
			facturaReporte.setPrecioUnitVenta(kardex.getPrecio());

			facturaReporte = egresoService.asignar(detalleEgreso,
					facturaReporte, egreso.getTipodocumento()
							.getTipodocumentoid());

			detalleEgreso.setCantidad(facturaReporte.getCantidad());
			detalleEgreso.setPreciocosto(kardex.getPrecio());
			detalleEgreso.setPrecioventa(facturaReporte.getPrecioUnitVenta());
			detalleEgreso.setIva(producto.getIva());
			detalleEgreso.setPromocion(facturaReporte.isPromocion());
			detalleEgreso.setEliminar(facturaReporte.isEliminar());

			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, facturaReporte, "add");

			facturaReportes.add(facturaReporte);
			egreso.addDetalleegreso(detalleEgreso);

			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"INSERTÓ DETALLE", "INSERTO: " + producto.getEan()));
			cancelar();
			producto = new Producto();
			motivoBaja = new Motivobaja();
			listProductos = new ArrayList<Producto>();
		} else
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR",
					"INGRESE UNA CANTIDAD MENOR O IGUAL A LA EXISTENTE: "
							+ cantidad + " O MAYOR QUE CERO"));
	}

	public void obtenerBodega() {
		Local local = localService.obtenerPorLocalId(egreso.getLocal()
				.getLocalid());
		if (local.getBodegalocals() != null
				&& !local.getBodegalocals().isEmpty())
			bodega = local.getBodegalocals().get(0).getBodega();
	}

	public void obtenerFila(CellEditEvent event) {
		fila = event.getRowIndex();
	}

	public void obtenerProductos() {
		if (!nombreProducto.equals(null))
			listProductos = productoService.obtenerPorLocal(nombreProducto
					.toUpperCase(), egreso.getLocal().getLocalid());
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	public void setCantidad(Integer cantidad) {
		this.cantidad = cantidad;
	}

	public void setCantidadFacturaCalculos(
			CantidadFactura cantidadFacturaCalculos) {
		this.cantidadFacturaCalculos = cantidadFacturaCalculos;
	}

	public void setCantidadFacturaPresentar(
			CantidadFactura cantidadFacturaPresentar) {
		this.cantidadFacturaPresentar = cantidadFacturaPresentar;
	}

	public void setEgreso(Egreso egreso) {
		this.egreso = egreso;
	}

	public void setFacturaReporte(FacturaReporte facturaReporte) {
		this.facturaReporte = facturaReporte;
	}

	public void setFacturaReportes(List<FacturaReporte> facturaReportes) {
		this.facturaReportes = facturaReportes;
	}

	public void setListaLocales(List<Local> listaLocales) {
		this.listaLocales = listaLocales;
	}

	public void setListaMotivoBajas(List<Motivobaja> listaMotivoBajas) {
		this.listaMotivoBajas = listaMotivoBajas;
	}

	public void setListProductos(List<Producto> listProductos) {
		this.listProductos = listProductos;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public void setMotivoBaja(Motivobaja motivoBaja) {
		this.motivoBaja = motivoBaja;
	}

	public void setNombreProducto(String nombreProducto) {
		this.nombreProducto = nombreProducto;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	public void setProducto(Producto producto) {
		this.producto = producto;
	}

	private void xxx() {
		egreso = new Egreso();
		egreso.setLocal(new Local());
		egreso.setEntradas(new ArrayList<Entrada>());
		egreso.setDetalleegresos(new ArrayList<Detalleegreso>());
		egreso.setTipodocumento(tipoDocumentoService.obtenerPorId(11));
		egreso.setCodigodocumento(tipoDocumentoService
				.obtenerPorId(11)
				.getAbreviatura()
				.concat("-")
				.concat(String.format("%010d",
						parametro.getSecuenciabajainventario() + 1)));

	}

}